package com.sui.bigdata.flink.sql.function.util;

import java.io.UnsupportedEncodingException;
import java.security.NoSuchAlgorithmException;

import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;

public class SimpleAES {
    private static final String Algorithm = "AES";
    private static final String CHARSET = "UTF-8";
    private static final String ALGORITHM_ECB = "AES/ECB/PKCS5Padding";

    /**
     * 加密
     *
     * @param plainText 明文
     * @param passwd
     * @return
     * @throws Exception
     */
    public static String encrypt(String plainText, String passwd) throws Exception {
        try {
            return toHex(encrypt(plainText.getBytes("UTF-8"), passwd));
        } catch (UnsupportedEncodingException e) {
            throw new UnsupportedEncodingException("SimpleAES encrypt UnsupportedEncodingException:" + e.getMessage());
        } catch (Exception e) {
            throw new Exception("SimpleAES encrypt Exception:" + e.getMessage());
        }
    }


    /**
     * 解密 以String密文输入,String明文输出
     *
     * @param cipherText
     * @return
     * @throws Exception
     */
    public static String decrypt(String cipherText, String passwd) throws Exception {
        try {
            byte[] bytes = decrypt(hexTobytes(cipherText), passwd);
            return new String(bytes, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            throw new Exception("SimpleAES decrypt exceptioon:" + e.getMessage());
        }
    }

    /**
     * 加密以byte[]明文输入,byte[]密文输出
     *
     * @param byteS
     * @return
     * @throws Exception
     */
    public static byte[] encrypt(byte[] byteS, String pwd) throws Exception {

        byte[] byteFina = null;
        Cipher cipher;
        try {
            cipher = Cipher.getInstance(Algorithm);

            SecretKeySpec keySpec = new SecretKeySpec(getKey(pwd), "AES");

            cipher.init(Cipher.ENCRYPT_MODE, keySpec);
            byteFina = cipher.doFinal(byteS);
        } catch (Exception e) {
            throw new Exception("SimpleAES Encrypt exceptioon:" + e.getMessage());
        } finally {
            cipher = null;
        }

        return byteFina;
    }

    /**
     * 解密以byte[]密文输入,以byte[]明文输出
     *
     * @param byteD
     * @return
     * @throws Exception
     */
    public static byte[] decrypt(byte[] byteD, String pwd) throws Exception {
        Cipher cipher;
        byte[] byteFina = null;
        try {
            cipher = Cipher.getInstance(Algorithm);

            SecretKeySpec keySpec = new SecretKeySpec(getKey(pwd), "AES");

            cipher.init(Cipher.DECRYPT_MODE, keySpec);

            byteFina = cipher.doFinal(byteD);

        } catch (Exception e) {
            throw new Exception(e);
        } finally {
            cipher = null;
        }
        return byteFina;
    }

    private static byte[] getKey(String password) throws UnsupportedEncodingException {
        if (password.length() > 16)
            password = password.substring(0, 16);
        else if (password.length() < 16) {
            int count = (16 - password.length());
            for (int i = 0; i < count; i++) {
                password += "0";
            }
        }

        return password.getBytes("UTF-8");
    }


    /**
     * Convert byte array to hex string
     */
    public static String toHex(byte[] bytes) {
        StringBuffer sb = new StringBuffer(bytes.length * 3);
        for (int i = 0; i < bytes.length; i++) {
            int val = ((int) bytes[i]) & 0xff;
            if (val < 16)
                sb.append("0");

            sb.append(Integer.toHexString(val));

        }

        return sb.toString();
    }

    /**
     * Convert hex string to byte array
     *
     * @param str
     * @return
     */
    public static byte[] hexTobytes(String str) {
        int l = str.length();
        if ((l % 2) != 0) {
            throw new IllegalArgumentException("长度不是偶数!");
        }
        byte[] bytes = new byte[l / 2];
        for (int i = 0; i < l; i = i + 2) {
            String item = str.substring(i, i + 2);
            bytes[i / 2] = (byte) Integer.parseInt(item, 16);
        }

        return bytes;
    }

    public static String ssjFeideeUserdecrypt(String input, String key) throws Exception {
        SecretKeySpec keySpec = new SecretKeySpec(keyBytes(key,16), Algorithm);
        Cipher cipher = Cipher.getInstance(ALGORITHM_ECB);
        cipher.init(Cipher.DECRYPT_MODE, keySpec);
        byte[] byteFinal = cipher.doFinal(hexTobytes(input));
        return new String(byteFinal,CHARSET);
    }

    /**
     * @param key 字节种子
     * @param byteLen 需要生成的字节长度：16 或 24 或 32 字节
     * @return
     * @throws UnsupportedEncodingException
     */
    private static byte[] keyBytes(String key, int byteLen) throws UnsupportedEncodingException {
        byte[] raw = new byte[byteLen];

        byte[] keyBytes = key.getBytes(CHARSET);
        for (int i = 0, j = 0; i < keyBytes.length; i++, j++) {
            if (j == raw.length) {
                j = 0;
            }
            raw[j] ^= keyBytes[i];
        }

        return raw;
    }
}
